unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, jpeg, ExtCtrls;

type
  Tform1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Image1: TImage;
    Label2: TLabel;
    GroupBox1: TGroupBox;
    Label6: TLabel;
    Label1: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label7: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label8: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    procedure Edit1KeyPress(Sender: TObject; var Key: Char);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Edit1Exit(Sender: TObject);

    { Private declarations }
  public
    j:integer;
    { Public declarations }
  end;

var
  a:integer; // contador '( '
  b:integer; // contador ') '
  form1: Tform1;
  LP: array[0..19] of Char; // LP letras presionadas
Const
  alfabeto = [#0..#31,'p'..'t','(',')','^','v','=','>','-'];
  SB = ['^','>','v','=']; //SB simbolos
  LT = ['p'..'t']; // LT letras
  PRIMEROS=['p'..'t','(','-'] ;
  CE = [#0..#31]; // Caracteres Especiales
implementation

{$R *.dfm}


procedure Tform1.Edit1KeyPress(Sender: TObject; var Key: Char);
  var
    h: integer;
    i: integer;
    m: boolean;
 begin

 {si el key no esta en el alfabeto
 entonces adopta el caracter null(#0) que no deja ingresar nada
 al campo de texto}
 while not(Key in alfabeto)do
    begin
      Key := #0;
      showmessage('Caracter Invalido');
    end;

      if self.Edit1.AutoSelect = true then
       self.Edit1.AutoSelect:= false;





    // si no esta en caracteres especiales lo almacena en el vector
    if not(key in CE ) then
     begin
      LP[j]:= key;
      j:=j+1;
     end;
    // si el key es igual al backspace y es la primera posicion del vector entonces no lo deja escribir
    if (key=#8) and  (LP[0]=' ')then
        key:=#0;
    // si en  la primera posicion del vector no se almacena nada que este en la constante primeros no lo deja ingresar
    // y borra la posicion
    if  not(LP[0] in PRIMEROS) then
    begin
      key:=#0;
      LP[0]:=' ';
      j:=0;
    end;
   // limpia el vector de a uno
  if key= #8 then
    begin
      j:=j-1;
      LP[j]:=' ';
    end;
 // almacena en contadores los numeros de parentesis presionados
 if key = '(' then
  a:= a+1;
  if key = ')' then
  b:= b+1;
  //comienza a controlar el vctor cuando j es igual o mayor a 2
   if j>=2then
      begin
      //no se pueden ingresar 2 letras seguidas
        if LP[j-2]in LT then
        begin
        if LP[j-1] in LT then
            begin
              key:=#0;
              j:=j-1;
               LP[j]:=' ';
            end;
        end;
        // no se puden ingresar dos simbolos seguidos que se enuentren en la constante SB
        if LP[j-2] in SB then
          begin
            if LP[j-1] in SB then
              begin
                key:=#0;
                 j:=j-1;
                 LP[j]:=' ';
              end;
          end;

          // se puede ingresar luego de un simbolo  solo lo que esta en la constante primeros
          if LP[j-2] in SB   then
            begin
              if not (LP[j-1] in PRIMEROS)then
                begin
                  key:=#0;
                  j:=j-1;
                  LP[j]:=' ';
                end;
          end;
          // lueg de un parentesis abierto no se puede ingresar nada que se encuentre en la constante SB
           if LP[j-2]='('   then
            begin
              if LP[j-1] in SB then
                begin
                  key:=#0;
                  j:=j-1;
                  LP[j]:=' ';
                end;
            end;
            // despues de un parentesis cerrado no puede ir una negacion  o una letra
            if LP[j-2] = ')'   then
              begin
                if (LP[j-1]='-') or (LP[j-1] in LT) or (LP[j-1]='(') then
                  begin
                      key:=#0;
                      j:=j-1;
                      LP[j]:=' ';
                end;
              end;
                   // luego de una negacion no puede ir un parentesis cerrrado
                   if LP[j-2] = '-'   then
            begin
              if LP[j-1] = ')' then
                begin
                      key:=#0;
                      j:=j-1;
                      LP[j]:=' ';
                end;
            end;


           // despues de una letra solo puede ir algo que se encuentra en la constante SB
          if LP[j-2] in LT   then
            begin
              if not (LP[j-1] in SB) then
                begin
                  if LP[j-1] <> ')' then
                    begin
                      key:=#0;
                      j:=j-1;
                      LP[j]:=' ';
                    end;
                end;
              end;
          //despues de una letra no puede ir un parentesis abierto
          if LP[j-2] in LT  then
            begin
              if LP[j-1]='(' then
                begin
                  key:=#0;
                  j:=j-1;
                  LP[j]:=' ';
                end;
            end;

            // en el caso que  se borre un parentesis abierto se decrementa su contador
               if (key =#8) and (LP[j-1]='(') then
                  a:= a -1;
                    // en el caso que  se borre un parentesis cerrado se decrementa su contador
                  if (key =#8) and (LP[j-1]=')') then
                  b:= b -1;
      end;

   // equilibrio de parentesis
   if key =')' then
      begin
          if not(b<= a) then
           begin
             key:=#0;
             j:=j-1;
             LP[j]:=' ';
             b:= b -1;
          end;
    end;








end;





















procedure Tform1.FormCreate(Sender: TObject);
var
  i: integer;
begin
{es for lo que hace es inicializar el array LP
 cada vez que arranca; y la variable j tambien se inicializa
 para almacenar las letras presionadas}
  for i:=1 to 20 do
    LP[i]:=' ';
  j:=0;
  a:=0;
  b:=0;
end;

procedure Tform1.Button1Click(Sender: TObject);
begin
{salir del programa}
Form1.Close;
end;
procedure Tform1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
{bueno como no sabemos como hacer que la imagen se adapte al form
cuando se la estira decidimos que cuando se agrande el for y el mouse
pase por ensima la imagen se agrande un poco}
image1.Width:= form1.Width;
image1.Height:= form1.Height;
end;
// si los parentesis no estan equilibrados a la hora decambiar el foco salta el cartel
procedure Tform1.Edit1Exit(Sender: TObject);
begin
    if a <> b then
      begin
        self.Edit1.SetFocus;
        showmessage('falta cerrar parentesis');
     end;

end;
end.



